[코담]
웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트
03 Todo 목록 화면 및 뷰 상세 설명 | ✅저자: 이유정(박사)
✅ 3. Todo 목록 화면 및 뷰 상세 설명
1️⃣ 목록을 보여주는 뷰: TodoListView
todo/ views.py
class TodoListView(LoginRequiredMixin, ListView):
model = Todo
template_name = "todo/todo_list.html"
context_object_name = "todos"
paginate_by = 5
def get_queryset(self):
queryset = Todo.objects.filter(author=self.request.user)
# 🔍 검색 필터
query = self.request.GET.get("q")
if query:
queryset = queryset.filter(name__icontains=query)
# ✅ 완료 상태 필터
complete_filter = self.request.GET.get("complete")
if complete_filter == "complete":
queryset = queryset.filter(complete=True)
elif complete_filter == "incomplete":
queryset = queryset.filter(complete=False)
# 📊 정렬 옵션
sort = self.request.GET.get("sort")
if sort == "exp":
queryset = queryset.order_by("-exp")
elif sort == "complete_date":
queryset = queryset.order_by("-completed_at")
else:
queryset = queryset.order_by("-created_at") # 기본 정렬
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["query"] = self.request.GET.get("q", "")
context["complete_filter"] = self.request.GET.get("complete", "")
context["sort"] = self.request.GET.get("sort", "")
return context
🔎 기능 요약
- 로그인한 사용자(author)의 할 일만 가져옴
- 검색어로 필터링
- 완료 여부로 필터링
- 정렬 옵션 제공 (생성일, 경험치, 완료일 등)
- 페이지네이션 기능 탑재 (5개씩)
2️⃣ 템플릿: todo/templates/todo/todo_list.html
🧩 기본 구조
{% extends "todo/include/base.html" %}
{% block title %}할일 목록{% endblock %}
- 전체 레이아웃은
base.html
을 상속 - 검색 필터, 추가 버튼, 목록 카드, 페이징, 삭제 모달 등 포함
🔍 검색/필터/정렬 폼
<form method="get">
<input type="search" name="q" value="{{ query }}" ...>
<select name="complete">...</select>
<select name="sort">...</select>
<button type="submit">검색</button>
</form>
q
,complete
,sort
값을 통해 뷰에서 필터링 적용됨
➕ 새 할일 버튼
<a href="{% url 'todo:todo_create' %}">새 할 일</a>
✅ 목록 카드 UI
{% for todo in todos %}
<div>
<h2><a href="{% url 'todo:todo_detail' todo.id %}">{{ todo.name }}</a></h2>
<p>{{ todo.description }}</p>
<a href="{% url 'todo:todo_update' todo.id %}">수정</a>
<button onclick="openDeleteModal({{ todo.id }})">삭제</button>
<form id="delete-form-{{ todo.id }}" method="post">...</form>
</div>
{% empty %}
<p>할 일이 없습니다.</p>
{% endfor %}
📄 페이징
{% if page_obj.has_previous %}<a href="?page=...">이전</a>{% endif %}
<span>페이지 {{ page_obj.number }} / {{ page_obj.paginator.num_pages }}</span>
{% if page_obj.has_next %}<a href="?page=...">다음</a>{% endif %}
ListView
의 페이징 객체를 이용한 UI
🗑 삭제 모달
- 삭제 버튼 클릭 시 모달이 뜨고, JS로 삭제 폼을 제출
<script>
function openDeleteModal(id) { ... }
function confirmDelete() { ... }
</script>
3️⃣ 연계 URL
# todo/urls.py
path("", TodoListView.as_view(), name="todo_list")
/todo/
로 접속 시todo_list.html
이 렌더링됨
✅ 전체 흐름 요약
- 사용자가
/todo/
접속 TodoListView
가 로그인 사용자에 맞는 할일 목록 필터링- 검색/필터/정렬 기능이 URL 파라미터로 적용됨
todo_list.html
에서 할 일 목록을 카드 형태로 표시- 수정/삭제/상세 보기로 각각 링크 연결됨
- 삭제는 JS 모달을 통해 안전하게 처리
✅ Tip:
get_queryset()
으로 로직을 분기하므로, 나중에 조건부 필터/검색/정렬을 자유롭게 커스터마이징 가능!